import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.Factory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Quickstart {

    private static final transient Logger log = LoggerFactory.getLogger(Quickstart.class);


    public static void main(String[] args) {

        //加载配置文件:
        //ini配置文件中可以配置 用户、角色、权限
        //相当于数据库 存储了用户信息 zhangsan=123456
        //存储了角色 admin
        //存储了权限 admin角色所有拥有的权限
        //用户可以直接赋予权限
        Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");

        //获得到 SecurityManager:专门用来管理session
        SecurityManager securityManager = factory.getInstance();

        //设置 SecurityManager
        SecurityUtils.setSecurityManager(securityManager);

        //获取主题:主题相当于用户信息
        //在任何地方都可以获取这个 Subject
        Subject currentUser = SecurityUtils.getSubject();

        //获取会话:既然是session 就可以存放数据 获取数据 --->存放、获取用户信息
        Session session = currentUser.getSession();
        session.setAttribute("zhangsan", "123456");

        String value = (String) session.getAttribute("zhangsan");//123456

        if (value.equals("123456")) {//比较session中的数据
            log.info("从session中获取的数据是: [" + value + "]");
        }

        // 登录判断
        if (!currentUser.isAuthenticated()) { //身份认证 是否登录成功
            //将用户名、密码放到UsernamePasswordToken 中
            //这里是的张三、123456 和ini文件中的用户做比较
            UsernamePasswordToken token = new UsernamePasswordToken("root", "secret");
            token.setRememberMe(true);//记住我
            try {
                currentUser.login(token);//做登录操作
                //这里登录、认证失败 是报错 给开发者去做处理、拦截
            } catch (UnknownAccountException uae) { //账号不存在
                uae.printStackTrace();
                log.info("There is no user with username of " + token.getPrincipal());
            } catch (IncorrectCredentialsException ice) { //密码错误
                log.info("Password for account " + token.getPrincipal() + " was incorrect!");

            } catch (LockedAccountException lae) { //账号锁定shiro中应该是没有实现抛出的  需要开发者自己去抛出 判断是否锁定
                //锁定的逻辑是灵活的:1、登录5次锁定 2、登录3次锁定
                log.info("The account for username " + token.getPrincipal() + " is locked.  " +
                        "Please contact your administrator to unlock it.");
            }
            // ... catch more exceptions here (maybe custom ones specific to your application?
            catch (AuthenticationException ae) {
                //unexpected condition?  error?
            }
        }

        //currentUser.getPrincipal():用户名
        log.info("User [" + currentUser.getPrincipal() + "] logged in successfully.");

        //开始判断角色:
        if (currentUser.hasRole("admin")) {
            log.info("有 admin 角色: 后面就可以操作一些admin角色可以操作的事情。。。。");
        } else {
            log.info("没有 admin  角色.");
        }

        //判断权限:权限标识有各种形式 edit、user:add....只是字符串而已
        if (currentUser.isPermitted("update")) {
            log.info("有 update 权限.");
        } else {
            log.info("没有 update 权限.");
        }

        //也是一个权限验证 winnebago:drive:eagle5:一个权限字符串标识
        if (currentUser.isPermitted("winnebago:drive:eagle5")) {
            log.info("You are permitted to 'drive' the winnebago with license plate (id) 'eagle5'.  " +
                    "Here are the keys - have fun!");
        } else {
            log.info("Sorry, you aren't allowed to drive the 'eagle5' winnebago!");
        }

        //退出登录
        currentUser.logout();

        //系统关闭
        System.exit(0);
    }
}
